import os
import subprocess
import platform
import sys
import time
import requests
import json
import gradio as gr

# 全局变量存储会话ID，用于前端与后端的会话关联
session_id = None


# ------------------------------
# 后端服务管理模块
# ------------------------------
def validate_project_structure():
    """
    校验项目目录结构是否符合要求

    功能: 确保当前脚本所在的frontend_new目录与backend目录处于同级
    返回:
        - 布尔值: 目录结构是否有效
        - 字符串: backend目录路径
        - 字符串: 错误信息(若无效)
    """
    # 获取当前脚本的绝对路径
    current_script_path = os.path.abspath(__file__)
    # 提取前端目录路径
    frontend_new_dir = os.path.dirname(current_script_path)
    print(f"[目录校验] 当前脚本所在目录（frontend_new）：{frontend_new_dir}")

    # 推导项目根目录（frontend_new的父目录）
    project_root = os.path.dirname(frontend_new_dir)
    print(f"[目录校验] 推导的项目根目录：{project_root}")

    # 构建后端目录路径
    backend_dir = os.path.join(project_root, "backend")
    # 检查后端目录是否存在
    if os.path.exists(backend_dir) and os.path.isdir(backend_dir):
        print(f"[目录校验] ✅ backend 目录存在：{backend_dir}")
        return True, backend_dir, None
    else:
        error_msg = (
            f"[目录校验] ❌ backend 目录不存在！\n"
            f"          期望路径：{backend_dir}\n"
            f"          请确认项目结构是否正确（要求 frontend_new 与 backend 同级）"
        )
        return False, backend_dir, error_msg


def check_backend_health():
    """
    检查后端服务健康状态

    功能: 通过访问后端健康检查接口，验证服务是否正常运行
    返回: 布尔值 - 后端服务是否健康
    """
    try:
        # 访问后端健康检查接口
        response = requests.get("http://localhost:8001/health", timeout=5)
        if response.status_code == 200:
            print("[健康检查] ✅ 后端服务已启动并正常运行")
            return True
        else:
            print(f"[健康检查] ❌ 后端服务返回非200状态码: {response.status_code}")
            return False
    except requests.exceptions.RequestException as e:
        print(f"[健康检查] ❌ 无法连接到后端服务: {str(e)}")
        return False


def create_chat_session():
    """
    创建新的聊天会话并更新全局session_id

    功能: 调用后端接口创建新会话，将返回的会话ID存储到全局变量
    返回: 字符串 - 新创建的会话ID，若失败则返回None
    """
    global session_id
    try:
        # 发送创建会话请求
        response = requests.post(
            "http://localhost:8001/api/chat/session/new",
            headers={"Content-Type": "application/json"},
            json={"system_context": None},
            timeout=10
        )

        if response.status_code == 200:
            session_data = response.json()
            session_id = session_data.get("session_id")
            if session_id:
                print(f"[会话创建] ✅ 成功创建会话，ID: {session_id}")
                return session_id
            else:
                print("[会话创建] ❌ 响应中未包含会话ID")
                return None
        else:
            print(f"[会话创建] ❌ 创建会话失败，状态码: {response.status_code}")
            print(f"[会话创建] 响应内容: {response.text}")
            return None
    except requests.exceptions.RequestException as e:
        print(f"[会话创建] ❌ 创建会话时发生错误: {str(e)}")
        return None


def start_backend():
    """
    启动后端服务并初始化会话

    功能:
        1. 校验目录结构
        2. 根据操作系统执行相应的启动命令
        3. 等待服务启动并检查健康状态
        4. 创建聊天会话
    返回: 后端进程对象
    """
    # 校验目录结构
    is_valid, backend_dir, dir_error = validate_project_structure()
    if not is_valid:
        print(dir_error)
        sys.exit(1)

    # 后端启动命令
    backend_cmd = "uvicorn app.main:app --host 0.0.0.0 --port 8001 --reload"
    print(f"\n[后端启动] 🚀 即将执行的后端启动命令：\n          {backend_cmd}")
    print(f"[后端启动] 📍 执行目录：{backend_dir}")

    try:
        # 根据操作系统构建完整命令
        if platform.system() == "Windows":
            full_cmd = f"cd /d {backend_dir} && {backend_cmd}"
            print(f"\n[后端启动] 📌 Windows 系统执行命令：\n          {full_cmd}")
            backend_process = subprocess.Popen(full_cmd, shell=True)
        else:
            full_cmd = f"cd {backend_dir} && {backend_cmd}"
            print(f"\n[后端启动] 📌 Linux/macOS 系统执行命令：\n          {full_cmd}")
            backend_process = subprocess.Popen(full_cmd, shell=True, executable="/bin/bash")

        # 等待服务启动
        print("\n[后端启动] 等待服务启动...（约5秒）")
        time.sleep(5)

        # 检查服务健康状态并创建会话
        if check_backend_health():
            print("\n[会话创建] 开始创建新的聊天会话...")
            create_chat_session()

        return backend_process

    except Exception as e:
        print(f"\n[后端启动] ❌ 发生错误：{str(e)}")
        sys.exit(1)


# ------------------------------
# 前端数据与功能模块
# ------------------------------
# 系统待处理任务数据 - 模拟银行零售贷款系统中需要处理的各类贷款审批任务
taskData = [
    {"id": "DK2023112001", "name": "个人住房贷款审批", "submitTime": "2023-11-20 14:30", "status": "待处理"},
    {"id": "DK2023112002", "name": "消费贷款审批", "submitTime": "2023-11-20 15:45", "status": "待处理"},
    {"id": "DK2023112003", "name": "经营贷款审批", "submitTime": "2023-11-20 16:20", "status": "待处理"},
]

# 逾期客户信息数据 - 模拟银行零售贷款系统中存在逾期情况的客户信息
overdueCustomerData = [
    {"name": "张明", "loanAmount": "¥500,000", "overdueDays": 35, "overdueAmount": "¥15,000"},
    {"name": "李婷", "loanAmount": "¥300,000", "overdueDays": 15, "overdueAmount": "¥8,000"},
]

# 系统消息提醒数据 - 模拟银行系统发送的各类通知信息
messageData = [
    {
        "id": 1,
        "title": "系统更新通知",
        "content": "系统将于今晚23:00-24:00进行例行维护更新",
        "time": "2023-11-20 10:00",
        "type": "system",
    },
    {
        "id": 2,
        "title": "风险预警提醒",
        "content": "客户张明贷款逾期超过30天，请及时处理",
        "time": "2023-11-20 09:30",
        "type": "warning",
    },
]

# 风险预警信息数据 - 模拟银行系统识别到的各类贷款风险预警
alertData = [
    {
        "id": 1,
        "title": "高风险预警",
        "content": "客户王建平近期出现多笔大额资金异常交易",
        "time": "2023-11-20 08:00",
        "level": "high",
    },
    {
        "id": 2,
        "title": "中风险预警",
        "content": "客户刘芳贷款即将到期，请提前通知",
        "time": "2023-11-19 16:30",
        "level": "medium",
    },
]


def convert_to_dataframe_format(data, keys):
    """
    数据格式转换工具

    功能: 将对象数组转换为Gradio Dataframe可直接显示的二维列表格式
    参数:
        data: 包含字典的列表，原始数据集合
        keys: 需要提取的字段列表，定义数据展示的顺序和内容
    返回: 二维列表，每个子列表对应一条数据的指定字段值
    """
    return [[item[key] for key in keys] for item in data]


def export_data():
    """
    数据导出功能

    功能: 模拟处理数据导出操作
    返回: 导出成功的提示信息
    """
    return "数据已导出成功！"


# 存储AI对话历史记录，格式为[(问题, 回答), ...]
chat_history = []


def api_request(message):
    """
    后端API调用工具

    功能: 使用全局session_id向后端发送消息并获取响应
    参数:
        message: 用户输入的消息内容
    返回: 后端响应的JSON数据，若失败则返回None
    """
    global session_id
    # 检查会话ID是否存在，不存在则尝试重新创建
    if not session_id:
        print("[消息发送] ❌ 会话ID不存在，尝试重新创建...")
        session_id = create_chat_session()
        if not session_id:
            return None

    # 后端API地址
    url = "http://localhost:8001/api/chat/send"
    # 请求头设置
    headers = {"Content-Type": "application/json"}
    # 请求数据
    payload = {
        "message": message,
        "session_id": session_id
    }

    try:
        # 发送请求
        response = requests.post(
            url,
            headers=headers,
            data=json.dumps(payload),
            timeout=100
        )

        if response.status_code == 200:
            print("[消息发送] ✅ 消息发送成功")
            return response.json()
        else:
            print(f"[消息发送] ❌ 接口返回错误状态码: {response.status_code}")
            print(f"[消息发送] 响应内容: {response.text}")
            return None

    except requests.exceptions.RequestException as e:
        print(f"[消息发送] ❌ 请求发生错误: {str(e)}")
        return None


def call_ai(question):
    """
    AI对话处理逻辑

    功能:
        1. 验证用户输入
        2. 构建包含历史对话的上下文
        3. 调用后端API获取回答
        4. 更新对话历史并返回
    参数:
        question: 用户输入的问题
    返回: 更新后的对话历史列表
    """
    # 验证输入是否为空
    if not question.strip():
        return chat_history

    # 构建包含历史对话的消息列表，用于上下文理解
    messages = []
    for q, a in chat_history:
        messages.append({"role": "user", "content": q})
        messages.append({"role": "assistant", "content": a})
    messages.append({"role": "user", "content": question})

    # 调用后端AI接口获取回答
    result = api_request(message=question)

    # 更新对话历史
    chat_history.append((question, result.get('response') if result else "抱歉，无法获取回答"))
    return chat_history


# ------------------------------
# 前端界面样式与布局
# ------------------------------
# 自定义CSS样式 - 控制界面元素的外观和布局
custom_css = """
/* 全局样式设置 */
body {
    background-color: #f9fafb !important;
    font-family: 'Inter', system-ui, sans-serif;
    margin: 0;
    padding: 0;
}

/* 导航栏样式 */
.header-container {
    background-color: #0f4c81;
    color: white;
    padding: 1rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
    box-sizing: border-box;
}

/* 标题和导航按钮容器 */
.title-nav-container {
    display: flex;
    align-items: center;
    gap: 2rem;
}

/* 系统标题样式 */
.app-title {
    font-size: 1.25rem;
    font-weight: bold;
    margin: 0;
    color: white !important;
}

/* 导航标签容器 */
.nav-tabs {
    display: flex;
    background-color: #0b3a5e;
    border-radius: 0.25rem 0.25rem 0 0;
    overflow: hidden;
    margin: 0;
}

/* 导航标签基础样式 */
.nav-tab {
    padding: 0.5rem 1rem;
    font-size: 0.875rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    color: white;
}

/* 激活状态的导航标签 */
.nav-tab.active {
    background-color: white;
    color: #0f4c81;
    font-weight: medium;
}

/* 搜索框容器 */
.search-container {
    display: flex;
    justify-content: center;
    flex: 1;
    padding: 0 1rem;
    margin: 0 1rem;
}

/* 搜索框样式 */
.search-input {
    background-color: #0b3a5e;
    border: 1px solid #082a46;
    border-radius: 0.375rem;
    padding: 0.5rem 0.5rem 0.5rem 2rem;
    color: white;
    font-size: 0.875rem;
    width: 100%;
    max-width: 25rem;
    background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>');
    background-repeat: no-repeat;
    background-size: 16px;
    background-position: 0.75rem center;
}

/* 用户信息容器 */
.user-info-container {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    min-width: fit-content;
}

/* 用户信息样式 */
.user-info {
    display: flex;
    align-items: center;
}

/* 用户头像样式 */
.avatar {
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    margin-right: 0.5rem;
}

/* 用户名样式 */
.user-name {
    font-size: 0.875rem;
    margin-right: 0.5rem;
    color: white !important;
}

/* 主内容区域布局 */
.main-content {
    padding: 1rem;
    display: flex;
    gap: 1rem;
    width: 100%;
    box-sizing: border-box;
}

/* 卡片容器样式 */
.card {
    background: white;
    border-radius: 0.5rem;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
    margin-bottom: 1rem;
    overflow: hidden;
}

/* 卡片头部样式 */
.card-header {
    padding: 0.5rem;
    border-bottom: 1px solid #e5e7eb;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

/* 卡片标题样式 */
.card-title {
    font-size: 1rem;
    font-weight: medium;
    color: #111827;
    margin: 0;
}

/* 按钮样式 */
.btn {
    background-color: #0f4c81;
    color: white;
    border: none;
    border-radius: 0.375rem;
    padding: 0.5rem 1rem;
    font-size: 0.875rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

/* 按钮图标样式 */
.btn i {
    color: white !important;
}

/* 数据表格容器 */
.dataframe-container {
    padding: 0 1rem 1rem;
}

/* 数据表格样式 */
.dataframe {
    width: 100% !important;
    border-collapse: collapse;
    font-size: 0.875rem;
}

/* 表格头部样式 */
.dataframe th {
    background-color: #f9fafb;
    color: #6b7280;
    text-align: left;
    padding: 0.75rem;
    border-bottom: 1px solid #e5e7eb;
}

/* 表格单元格样式 */
.dataframe td {
    padding: 0.75rem;
    border-bottom: 1px solid #e5e7eb;
}

/* 列表容器样式 */
.list-container {
    padding: 0.75rem;
}

/* 消息卡片样式 */
.msg-card {
    border: 1px solid #e5e7eb;
    border-radius: 0.5rem;
    padding: 0.75rem;
    background-color: #f9fafb;
    margin-bottom: 0.75rem;
    display: flex;
}

/* 消息图标样式 */
.msg-icon {
    width: 1.25rem;
    height: 1.25rem;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-right: 0.75rem;
    margin-top: 0.25rem;
}

/* 系统消息图标样式 */
.msg-system {
    background-color: #fef3c7;
    color: #d97706;
}

/* 警告消息图标样式 */
.msg-warning {
    background-color: #fee2e2;
    color: #b91c1c;
}

/* 消息标题样式 */
.msg-title {
    font-size: 0.875rem;
    font-weight: medium;
    margin-bottom: 0.25rem;
}

/* 消息内容样式 */
.msg-desc {
    font-size: 0.75rem;
    color: #4b5563;
    margin-bottom: 0.25rem;
}

/* 消息时间样式 */
.msg-time {
    font-size: 0.7rem;
    color: #6b7280;
}

/* 感叹号图标样式 */
.exclamation-icon {
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    background-color: #0f4c81;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
    margin-right: 0.5rem;
}

/* 感叹号图标颜色 */
.exclamation-icon i {
    color: white !important;
}

/* 导出按钮容器 */
.export-btn-container {
    display: flex;
    justify-content: flex-end;
    width: 100%;
}

/* AI对话按钮样式 */
#ai-button {
    position: fixed !important;
    bottom: 2rem;
    right: 2rem;
    width: 4rem !important;
    height: 4rem !important;
    border-radius: 50% !important;
    background-color: #0f4c81 !important;
    color: white !important;
    border: none !important;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2) !important;
    cursor: pointer !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    font-size: 1.8rem !important;
    z-index: 100 !important;
    transition: all 0.2s ease !important;
    padding: 0 !important;
    min-width: auto !important;
}

#ai-button:hover {
    background-color: #0b3a5e !important;
    transform: scale(1.05) !important;
}

/* AI对话模态框样式 */
.ai-modal {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 1000;
    align-items: center;
    justify-content: center;
}

.ai-modal-content {
    background-color: white;
    width: 90%;
    max-width: 600px;
    border-radius: 0.5rem;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    overflow: hidden;
}

/* 模态框头部样式 - 控制关闭按钮位置 */
.ai-modal-header {
    padding: 1rem;
    background-color: #0f4c81;
    color: white;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

/* AI助手标题样式 - 设置为白色 */
.ai-modal-header h3 {
    color: white !important;
    margin: 0;
}

/* 小尺寸关闭按钮样式 */
.ai-modal-header .btn {
    padding: 0.3rem 0.6rem;
    font-size: 1rem;
}

.ai-modal-body {
    padding: 1rem;
}
"""


def create_interface():
    """
    创建Gradio前端界面

    功能: 构建银行零售贷款系统的前端界面，包含导航栏、数据展示区和AI对话功能
    返回: Gradio Blocks对象
    """
    with gr.Blocks(css=custom_css, title="XX银行零售贷款系统") as demo:
        # 创建状态组件用于显示操作结果（隐藏状态）
        export_status = gr.Textbox(label="操作状态", visible=False)

        # 引入Font Awesome图标库
        gr.HTML("""
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
        """)

        # 导航栏区域 - 包含系统标题、导航标签、搜索框和用户信息
        with gr.Row(elem_classes="header-container"):
            with gr.Column(scale=3, elem_classes="title-column"):
                gr.Markdown("""
                    <div class='title-nav-container'>
                        <h1 class='app-title'>XX银行零售贷款系统</h1>
                        <div class='nav-tabs'>
                            <div class='nav-tab active'>首页 <span class='ml-1'>×</span></div>
                            <div class='nav-tab'>贷款申请 <span class='ml-1'>×</span></div>
                        </div>
                    </div>
                """)

            with gr.Column(scale=4, elem_classes="search-container"):
                # 搜索框组件
                gr.Markdown("""
                    <input type='text' placeholder='搜索菜单' class='search-input'>
                """)

            with gr.Column(scale=2, elem_classes="user-info-container"):
                # 用户信息展示
                gr.Markdown("""
                    <div class='user-info'>
                        <img src='https://space.coze.cn/api/coze_space/gen_image?image_size=square&prompt=bank%20employee%20avatar%2C%20male%2C%20professional%20looking&sign=1869ec47c7bc9cbd26b803e32bec4a31' 
                             alt='用户头像' class='avatar'>
                        <span class='user-name'>测试用户</span>
                        <i class='fa-solid fa-chevron-down' style='color: white; font-size: 0.75rem;'></i>
                    </div>
                """)

        # 主内容区域 - 分为左右两栏
        with gr.Row(elem_classes="main-content"):
            # 左侧主内容区（占比7/12）
            with gr.Column(scale=7):
                # 待办任务卡片
                with gr.Column(elem_classes="card"):
                    with gr.Row(elem_classes="card-header"):
                        gr.Markdown(
                            "<h2 class='card-title' style='color: #0f4c81; border-bottom: 2px solid #0f4c81; padding-bottom: 0.5rem;'>我的待办 (12)</h2>")
                        gr.Markdown(
                            "<h2 class='card-title' style='color: #6b7280; padding-bottom: 0.5rem;'>我的已办 (156)</h2>")

                    with gr.Column(elem_classes="dataframe-container"):
                        gr.Dataframe(
                            value=convert_to_dataframe_format(taskData, ["id", "name", "submitTime", "status"]),
                            headers=["业务编号", "任务名称", "提交时间", "状态"],
                            elem_classes="dataframe",
                            interactive=False
                        )

                # 逾期客户信息卡片
                with gr.Column(elem_classes="card"):
                    with gr.Row(elem_classes="card-header"):
                        with gr.Column(scale=8):
                            gr.Markdown("""
                                <h2 class='card-title'>
                                    <span class='exclamation-icon'><i class='fa-solid fa-exclamation-circle'></i></span>
                                    逾期客户信息
                                </h2>
                            """)

                        with gr.Column(scale=2, elem_classes="export-btn-container"):
                            # 隐藏的导出按钮（用于功能绑定）
                            hidden_export_btn = gr.Button("导出数据", visible=False)
                            # 自定义导出按钮HTML
                            gr.HTML("""
                                <button id="export-button" class="btn">
                                    <i class='fa-solid fa-download'></i> 导出数据
                                </button>
                            """)
                            # 绑定自定义按钮到Gradio按钮
                            gr.HTML("""
                                <script>
                                    document.addEventListener('DOMContentLoaded', function() {
                                        const htmlBtn = document.getElementById('export-button');
                                        const gradioBtns = document.querySelectorAll('.gr-button');
                                        let gradioBtn = null;

                                        for (let btn of gradioBtns) {
                                            if (btn.textContent.trim() === '导出数据') {
                                                gradioBtn = btn;
                                                break;
                                            }
                                        }

                                        if (htmlBtn && gradioBtn) {
                                            htmlBtn.addEventListener('click', function() {
                                                gradioBtn.click();
                                            });
                                        }
                                    });
                                </script>
                            """)
                            # 绑定导出按钮事件
                            hidden_export_btn.click(
                                fn=export_data,
                                outputs=[export_status]
                            )

                    with gr.Column(elem_classes="dataframe-container"):
                        gr.Dataframe(
                            value=convert_to_dataframe_format(overdueCustomerData,
                                                              ["name", "loanAmount", "overdueDays", "overdueAmount"]),
                            headers=["客户姓名", "贷款金额", "逾期天数", "逾期金额"],
                            elem_classes="dataframe",
                            interactive=False
                        )

            # 右侧边栏区域（占比5/12）
            with gr.Column(scale=5):
                # 消息提醒卡片
                with gr.Column(elem_classes="card"):
                    with gr.Row(elem_classes="card-header"):
                        gr.Markdown("<h2 class='card-title'>消息提醒</h2>")
                        gr.Markdown(
                            "<a href='#' style='color: #0f4c81; font-size: 0.875rem; text-decoration: none;'>查看更多</a>")

                    with gr.Column(elem_classes="list-container"):
                        # 循环展示消息提醒数据
                        for msg in messageData:
                            icon_cls = "msg-system" if msg["type"] == "system" else "msg-warning"
                            icon_text = "⚠" if msg["type"] == "system" else "🔴"
                            gr.Markdown(f"""
                                <div class='msg-card'>
                                    <div class='msg-icon {icon_cls}'>{icon_text}</div>
                                    <div>
                                        <div class='msg-title'>{msg['title']}</div>
                                        <div class='msg-desc'>{msg['content']}</div>
                                        <div class='msg-time'>{msg['time']}</div>
                                    </div>
                                </div>
                            """)

                # 预警信息卡片
                with gr.Column(elem_classes="card"):
                    with gr.Row(elem_classes="card-header"):
                        gr.Markdown("<h2 class='card-title'>预警信息</h2>")

                    with gr.Column(elem_classes="list-container"):
                        # 循环展示风险预警信息
                        for alert in alertData:
                            icon_cls = "msg-warning" if alert["level"] == "high" else "msg-system"
                            icon_text = "🔴" if alert["level"] == "high" else "⚠"
                            gr.Markdown(f"""
                                <div class='msg-card'>
                                    <div class='msg-icon {icon_cls}'>{icon_text}</div>
                                    <div>
                                        <div class='msg-title'>{alert['title']}</div>
                                        <div class='msg-desc'>{alert['content']}</div>
                                        <div class='msg-time'>{alert['time']}</div>
                                    </div>
                                </div>
                            """)

        # AI对话功能模块 - 模态框形式
        with gr.Column(elem_classes="ai-modal", visible=False) as ai_modal:
            with gr.Column(elem_classes="ai-modal-content"):
                with gr.Row(elem_classes="ai-modal-header"):
                    gr.Markdown("<h3>AI助手</h3>")
                    close_btn = gr.Button("关闭", elem_classes="btn")

                with gr.Column():
                    chat_display = gr.Chatbot(label="对话历史", height=600)
                    question = gr.Textbox(label="请输入问题", lines=4)
                    submit_btn = gr.Button("发送", elem_classes="btn")

                # 绑定发送按钮事件
                submit_btn.click(
                    fn=call_ai,
                    inputs=[question],
                    outputs=[chat_display]
                )
                # 绑定回车键事件
                question.submit(
                    fn=call_ai,
                    inputs=[question],
                    outputs=[chat_display]
                )

                # 绑定关闭按钮事件
                close_btn.click(
                    fn=lambda: gr.update(visible=False),
                    outputs=ai_modal
                )

        # AI助手按钮 - 固定在页面右下角
        ai_button = gr.Button("🤖", elem_id="ai-button")
        ai_button.click(
            fn=lambda: gr.update(visible=True),
            outputs=ai_modal
        )

    return demo


# ------------------------------
# 程序入口
# ------------------------------
def main():
    """
    程序主入口函数

    功能:
        1. 显示系统信息
        2. 启动后端服务
        3. 创建并启动前端界面
        4. 处理服务终止逻辑
    """
    print("=" * 60)
    print("🏠 银行零售贷款系统（整合版）")
    print("=" * 60)
    print("功能说明：")
    print("1. 自动校验项目目录结构（确保 frontend_new 与 backend 同级）")
    print("2. 自动启动后端服务")
    print("3. 启动命令：uvicorn app.main:app --host 0.0.0.0 --port 8001 --reload")
    print("4. 自动验证健康状态并创建会话ID")
    print("5. 运行前端Gradio界面")
    print("=" * 60 + "\n")

    # 启动后端服务
    print("[后端启动] 开始启动后端服务...\n")
    backend_process = start_backend()

    # 创建并启动前端界面
    print("\n[前端启动] 开始启动Gradio界面...")
    demo = create_interface()
    demo.launch(debug=True)

    # 等待后端进程结束
    try:
        backend_process.wait()
    except KeyboardInterrupt:
        print("\n[系统] 用户中断，正在停止服务...")
        backend_process.terminate()
        sys.exit(0)


if __name__ == "__main__":
    main()
